use libc::{c_char, c_int, c_void, size_t};
use std::ptr::null_mut;

pub const AVL_TREE_NULL: *mut c_void = null_mut();

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub enum AVLTreeNodeSide {
    AVL_TREE_NODE_LEFT = 0,
    AVL_TREE_NODE_RIGHT = 1,
}

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct AVLTreeNode {
    pub children: [*mut AVLTreeNode; 2],
    pub parent: *mut AVLTreeNode,
    pub key: AVLTreeKey,
    pub value: AVLTreeValue,
    pub height: c_int,
}

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct AVLTree {
    pub root_node: *mut AVLTreeNode,
    pub compare_func: AVLTreeCompareFunc,
    pub num_nodes: c_int,
}

pub type AVLTreeCompareFunc = extern C fn(value1: AVLTreeValue, value2: AVLTreeValue) -> c_int;

#[no_mangle]
pub unsafe extern C fn avl_tree_new(compare_func: AVLTreeCompareFunc) -> *mut AVLTree {
    // Implementation of avl_tree_new in Rust
}

#[no_mangle]
pub unsafe extern C fn avl_tree_free(tree: *mut AVLTree) {
    // Implementation of avl_tree_free in Rust
}

#[no_mangle]
pub unsafe extern C fn avl_tree_insert(tree: *mut AVLTree, key: AVLTreeKey, value: AVLTreeValue) -> *mut AVLTreeNode {
    // Implementation of avl_tree_insert in Rust
}

#[no_mangle]
pub unsafe extern C fn avl_tree_remove(tree: *mut AVLTree, key: AVLTreeKey) -> c_int {
    // Implementation of avl_tree_remove in Rust
}

#[no_mangle]
pub unsafe extern C fn avl_tree_lookup(tree: *mut AVLTree, key: AVLTreeKey) -> AVLTreeValue {
    // Implementation of avl_tree_lookup in Rust
}

// ... other functions translated similarly
